Skip to content

Fix DSC_RESOURCE_PATH and add DSC_RESTRICTED_PATH#1636

Merged
SteveL-MSFT merged 10 commits into
PowerShell:mainfrom
SteveL-MSFT:dsc-restricted-path
Jul 23, 2026
Merged

Fix DSC_RESOURCE_PATH and add DSC_RESTRICTED_PATH#1636
SteveL-MSFT merged 10 commits into
PowerShell:mainfrom
SteveL-MSFT:dsc-restricted-path

Conversation

@SteveL-MSFT

@SteveL-MSFT SteveL-MSFT commented Jul 17, 2026

Copy link
Copy Markdown
Member

PR Summary

The behavior is that allow_env_override (true by default) restricts whether DSC_RESTRICTED_PATH or DSC_RESOURCE_PATH gets applied.

  • Add DSC_RESTRICTED_PATH which limits both manifest and exe discovery, this works by replacing the PATH env var
  • Update DSC_RESOURCE_PATH to be limited only to manifest discovery and not exe discovery by not overwriting PATH, DSC home path is added to PATH
  • Old tests were designed expecting the previous DSC_RESOURCE_PATH behavior, so searched and replaced them to use DSC_RESTRICTED_PATH instead
  • Added new tests, DSC_RESTRICTED_PATH takes precedence if DSC_RESOURCE_PATH is also defined

PR Context

Fix #1632

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses issue #1632 by separating “manifest discovery” from “executable discovery” behavior when environment variables are set, introducing DSC_RESTRICTED_PATH (restrict both) and adjusting DSC_RESOURCE_PATH (restrict manifests only).

Changes:

  • Add DSC_RESTRICTED_PATH and give it precedence over DSC_RESOURCE_PATH.
  • Update command discovery so DSC_RESOURCE_PATH no longer overwrites PATH (preventing extension executable lookup regressions).
  • Update/extend Pester tests to reflect the new environment-variable semantics.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
lib/dsc-lib/src/discovery/command_discovery.rs Implements DSC_RESTRICTED_PATH precedence and adjusts how PATH is handled during discovery.
lib/dsc-lib-jsonschema/.versions.json Bumps JSON schema patch version metadata to V3_2_3.
dsc/tests/dsc_set.tests.ps1 Updates tests to use DSC_RESTRICTED_PATH where prior behavior depended on PATH replacement.
dsc/tests/dsc_resource_manifest.tests.ps1 Switches manifest-related test isolation to DSC_RESTRICTED_PATH.
dsc/tests/dsc_resource_list.tests.ps1 Updates resource listing tests to use DSC_RESTRICTED_PATH (but currently contains a typo).
dsc/tests/dsc_resource_input.tests.ps1 Updates resource input tests to use DSC_RESTRICTED_PATH.
dsc/tests/dsc_resource_deprecated.tests.ps1 Updates deprecated resource tests to use DSC_RESTRICTED_PATH.
dsc/tests/dsc_extension_secret.tests.ps1 Updates secret/extension tests to use DSC_RESTRICTED_PATH.
dsc/tests/dsc_extension_manifest.tests.ps1 Updates extension manifest tests to use DSC_RESTRICTED_PATH.
dsc/tests/dsc_extension_import.tests.ps1 Updates extension import tests to use DSC_RESTRICTED_PATH.
dsc/tests/dsc_extension_discover.tests.ps1 Updates extension discovery tests to use DSC_RESTRICTED_PATH.
dsc/tests/dsc_discovery.tests.ps1 Adds new coverage for restricted vs resource path semantics (but currently has non-portable path construction).
dsc/tests/dsc_args.tests.ps1 Updates argument tests to use DSC_RESTRICTED_PATH.
dsc/tests/dsc_adapter.tests.ps1 Updates adapter-related tests to use DSC_RESTRICTED_PATH.
adapters/powershell/Tests/win_powershellgroup.tests.ps1 Updates Windows PowerShell adapter tests to use DSC_RESTRICTED_PATH.
adapters/powershell/Tests/win_powershell_cache.tests.ps1 Updates Windows PowerShell adapter cache tests to use DSC_RESTRICTED_PATH.

Comment thread lib/dsc-lib/src/discovery/command_discovery.rs
Comment thread lib/dsc-lib/src/discovery/command_discovery.rs Outdated
Comment thread dsc/tests/dsc_resource_list.tests.ps1
Comment thread dsc/tests/dsc_discovery.tests.ps1 Outdated
Comment thread dsc/tests/dsc_discovery.tests.ps1 Outdated
Comment thread dsc/tests/dsc_discovery.tests.ps1 Outdated
Copilot AI review requested due to automatic review settings July 20, 2026 20:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

lib/dsc-lib/src/discovery/command_discovery.rs:180

  • DSC_RESOURCE_PATH being set currently disables PATH mutation even when allow_env_override is false (the env var is ignored for discovery, but it still changes behavior). Gate this check on allow_env_override so PATH behavior is unchanged unless DSC_RESOURCE_PATH is actually being honored.
        } else if dsc_resource_path.is_none() { // if DSC_RESOURCE_PATH is used, we don't want to modify the PATH env var, as it is intended to be used for resource discovery only

Comment thread dsc/tests/dsc_discovery.tests.ps1
@tgauth

tgauth commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)
lib/dsc-lib/src/discovery/command_discovery.rs:180

  • DSC_RESOURCE_PATH being set currently disables PATH mutation even when allow_env_override is false (the env var is ignored for discovery, but it still changes behavior). Gate this check on allow_env_override so PATH behavior is unchanged unless DSC_RESOURCE_PATH is actually being honored.
        } else if dsc_resource_path.is_none() { // if DSC_RESOURCE_PATH is used, we don't want to modify the PATH env var, as it is intended to be used for resource discovery only

I think this might be a valid comment

@SteveL-MSFT

Copy link
Copy Markdown
Member Author

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
lib/dsc-lib/src/discovery/command_discovery.rs:180

  • DSC_RESOURCE_PATH being set currently disables PATH mutation even when allow_env_override is false (the env var is ignored for discovery, but it still changes behavior). Gate this check on allow_env_override so PATH behavior is unchanged unless DSC_RESOURCE_PATH is actually being honored.
        } else if dsc_resource_path.is_none() { // if DSC_RESOURCE_PATH is used, we don't want to modify the PATH env var, as it is intended to be used for resource discovery only

I think this might be a valid comment

I believe allow_env_override is literally "allow PATH env var to be overwritten". In this case DSC_RESOURCE_PATH doesn't overwrite PATH and instead is only used for resource discovery and PATH is still used for exe discovery. I guess the question is does allow_env_override affect both resource and exe PATH or literally just PATH. I'm thinking only the latter which is what I was conveying in the comment in the code.

@tgauth

tgauth commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

I believe allow_env_override is literally "allow PATH env var to be overwritten". In this case DSC_RESOURCE_PATH doesn't overwrite PATH and instead is only used for resource discovery and PATH is still used for exe discovery. I guess the question is does allow_env_override affect both resource and exe PATH or literally just PATH. I'm thinking only the latter which is what I was conveying in the comment in the code.

I see. Is the allow_env_override check on l. 143 necessary then? Put another way, is the difference in behavior depending on the value of DSC_RESOURCE_PATH.is_some() when allow_env_override is false by design?

@SteveL-MSFT

SteveL-MSFT commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@tgauth thinking about this further and to reduce complexity in the code and also for users to think through, I'm going to simply define allow_env_override to even allow using DSC_RESTRICTED_PATH or DSC_RESOURCE_PATH. I'll make the changes to the code for this. In this case, I think append_env_path is no longer needed since it doesn't do anything. The logic should be;

  1. if allow_env_override
    a. if DSC_RESTRICTED_PATH exists, use that for both resource manifest and exe discovery
    b. else if DSC_RESOURCE_PATH exists, use that just for resource manifest discovery
  2. else just use PATH for both resource manifest and exe discovery
  3. if not using DSC_RESTRICTED_PATH or allow_env_override is false
    a. append DSC Home folder to end of PATH

I think the current PR covers this behavior. However, there's one change I need to make. Even if DSC_RESOURCE_PATH is used, DSC Home needs to be added to PATH.

Copilot AI review requested due to automatic review settings July 22, 2026 16:59
@SteveL-MSFT
SteveL-MSFT force-pushed the dsc-restricted-path branch from 4491f09 to b24d1a7 Compare July 22, 2026 17:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

lib/dsc-lib/src/discovery/command_discovery.rs:184

  • DSC_RESOURCE_PATH being set influences PATH/resource-path handling even when allowEnvOverride is false. In that case, env override is ignored for discovery, but this branch still runs and prevents add_exe_home_to_path(paths) from adding the DSC exe home to the manifest search paths (and may still mutate PATH). Gate this branch on allow_env_override so env vars are truly ignored when policy disables them.
        } else if dsc_resource_path.is_some() {
            // just add exe home to PATH env var if not already in PATH env var
            let env_paths = env::var_os("PATH").map(|paths| env::split_paths(&paths).collect::<Vec<_>>()).unwrap_or_default();
            _ = add_exe_home_to_path(env_paths)?;
        } else {

Comment thread dsc/tests/dsc_discovery.tests.ps1
Comment thread dsc/tests/dsc_discovery.tests.ps1
Copilot AI review requested due to automatic review settings July 22, 2026 17:05
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

lib/dsc-lib/src/discovery/command_discovery.rs:186

  • When allowEnvOverride is false, DSC_RESOURCE_PATH is ignored for discovery (the else { ... } branch builds paths from the configured directories/PATH). However, later the else if dsc_resource_path.is_some() branch still runs, which means add_exe_home_to_path is applied only to the current PATH and does not add the exe home into paths. This makes behavior depend on whether DSC_RESOURCE_PATH merely exists (even when override is disabled) and can cause built-in manifests in the exe directory to be skipped when the exe home isn’t already in PATH.

Gate the “DSC_RESOURCE_PATH is set” branch on allow_env_override and on actually using that env var for discovery (similarly to the restricted-path branch), so the presence of the env var can’t change behavior when overrides are disabled.

        if resource_path_setting.allow_env_override && dsc_restricted_path.is_some() {
            // when using restricted path, intent is to isolate the search of manifests and executables to the restricted path
            // so we replace the PATH with the restricted path
            if let Ok(new_path) = env::join_paths(paths.clone()) {
                unsafe {
                    env::set_var("PATH", new_path);
                }
            } else {
                return Err(DscError::Operation(t!("discovery.commandDiscovery.failedJoinEnvPath").to_string()));
            }
        } else if dsc_resource_path.is_some() {
            // just add exe home to PATH env var if not already in PATH env var
            let env_paths = env::var_os("PATH").map(|paths| env::split_paths(&paths).collect::<Vec<_>>()).unwrap_or_default();
            _ = add_exe_home_to_path(env_paths)?;
        } else {
            // if exe home is not already in PATH env var then add it to env var and list of searched paths
            paths = add_exe_home_to_path(paths)?;

Copilot AI review requested due to automatic review settings July 22, 2026 17:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

lib/dsc-lib/src/discovery/command_discovery.rs:183

  • DSC_RESOURCE_PATH being set currently triggers PATH mutation even when allowEnvOverride is false. In that case the env var is ignored for manifest discovery (falls back to configured directories/PATH), but this else if dsc_resource_path.is_some() branch still calls add_exe_home_to_path(...) and can change PATH as a side effect. Gate this branch on resource_path_setting.allow_env_override so disabling env override fully disables env-var-driven PATH changes.
        } else if dsc_resource_path.is_some() {
            // just add exe home to PATH env var if not already in PATH env var
            let env_paths = env::var_os("PATH").map(|paths| env::split_paths(&paths).collect::<Vec<_>>()).unwrap_or_default();
            _ = add_exe_home_to_path(env_paths)?;

Copilot AI review requested due to automatic review settings July 22, 2026 22:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 22, 2026 22:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Comment thread lib/dsc-lib/src/discovery/command_discovery.rs
Copilot AI review requested due to automatic review settings July 22, 2026 22:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Comment thread lib/dsc-lib-jsonschema/.versions.json
Comment thread lib/dsc-lib/locales/en-us.toml Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 22, 2026 23:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Comment thread adapters/powershell/Tests/win_powershellgroup.tests.ps1
Comment thread adapters/powershell/Tests/win_powershell_cache.tests.ps1
Copilot AI review requested due to automatic review settings July 22, 2026 23:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

dsc/tests/dsc_discovery.tests.ps1:387

  • This test builds the manifest path using a hard-coded / separator (e.g. .../echo.dsc.resource.json). Use Join-Path for platform-independent paths to avoid failures on hosts where mixed separators are not normalized.
        $manifest1 = Get-Content -Raw -Path "$(Split-Path -Path $dscEcho.Source -Parent)/echo.dsc.resource.json" | ConvertFrom-Json -AsHashtable
        $manifest1.type = 'Test/RestrictedPathResource1'
        $manifest1.condition = "[not(equals(tryWhich('dscecho'), null()))]"
        Set-Content -Path (Join-Path $exePath1 'test.dsc.resource.json') -Value ($manifest1 | ConvertTo-Json -Depth 10)
        $manifest2 = Get-Content -Raw -Path "$(Split-Path -Path $dscEcho.Source -Parent)/echo.dsc.resource.json" | ConvertFrom-Json -AsHashtable

dsc/tests/dsc_discovery.tests.ps1:413

  • These Copy-Item paths are constructed via string concatenation with / (e.g. "$dscHome/psscript.dsc.resource.json"). Prefer Join-Path so the test remains path-separator agnostic across Windows/Linux/macOS.
        Copy-Item -Path "$dscHome/psscript.dsc.resource.json" -Destination "$testdrive"
        Copy-Item -Path "$dscHome/echo.dsc.resource.json" -Destination "$testdrive"
        Copy-Item -Path "$dscHome/dscecho*" -Destination "$testdrive"

Comment thread lib/dsc-lib/src/discovery/command_discovery.rs
@SteveL-MSFT
SteveL-MSFT added this pull request to the merge queue Jul 23, 2026
Merged via the queue into PowerShell:main with commit acdcf37 Jul 23, 2026
20 checks passed
@SteveL-MSFT
SteveL-MSFT deleted the dsc-restricted-path branch July 23, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Appx extension fails when DSC_RESOURCE_PATH is set

3 participants